package geppetto.cat.programs;


import geppetto.cat.alignments.Alignment;
import geppetto.cat.alignments.AlignmentEvaluator;
import geppetto.cat.alignments.AlignmentSymetrization;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.alignments.AlignmentEvaluator.Evaluation;
import geppetto.cat.common.StaticTools;
import geppetto.cat.corpus.BilingualCorpus;
import geppetto.cat.models.AbstractModel;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.zip.GZIPOutputStream;



public class SymmetrizeAlignments {

	public static void initializeStream(PrintStream[] alignmentStream,BilingualCorpus c,
			String alignmentName, String modelName, int size,
			String baseDir,
			double threshold, String format)
			throws IOException, FileNotFoundException {
		
		String forwardDirection = baseDir +"/"+modelName+"/"+c.getName()+"/"+
		size+"/"+threshold+"/"+format+"/";
		StaticTools.createDir(forwardDirection);
		alignmentStream[0] = new PrintStream(new GZIPOutputStream(new FileOutputStream(
				forwardDirection + "aligned." + alignmentName+".gz")), true, "UTF-8");
		alignmentStream[1] = new PrintStream(new FileOutputStream(
				forwardDirection + "aligned.0." + c.getSourceSufix()), true, "UTF-8");
		alignmentStream[2] = new PrintStream(new FileOutputStream(
				forwardDirection + "aligned.0." + c.getForeignSufix()), true, "UTF-8");
	}
	
	public static void initializeStream(PrintStream[] alignmentStream,BilingualCorpus c,
			String alignmentName, String modelName,
			String baseDir,
			double threshold, String format, int size)
			throws IOException, FileNotFoundException {
		
		String forwardDirection = baseDir +"/"+modelName+"/"+c.getName()+"/"+
		size + "/" + threshold + "/" + format + "/";
		StaticTools.createDir(forwardDirection);
		alignmentStream[0] = new PrintStream(new GZIPOutputStream(new FileOutputStream(
				forwardDirection + "aligned." + alignmentName+".gz")), true, "UTF-8");
		alignmentStream[1] = new PrintStream(new FileOutputStream(
				forwardDirection + "aligned.0." + c.getSourceSufix()), true, "UTF-8");
		alignmentStream[2] = new PrintStream(new FileOutputStream(
				forwardDirection + "aligned.0." + c.getForeignSufix()), true, "UTF-8");
	}
	
	public static AlignmentsSet getSymmetrizationAlignments(BilingualCorpus corpus, 
			byte sentenceSource, boolean projectPosteriors, 
			AbstractModel modelF,AbstractModel modelB, 
			String type, double threshold){
		
		
		
		int[] sentences = new int[corpus.getNumSentences(sentenceSource)];
		for (int i = 0; i < sentences.length; i++) {
			sentences[i] = i;
		}
		AlignmentsSet predictedF = modelF.posteriorAlignments(sentences,
				sentenceSource, 1f , projectPosteriors,false);
		AlignmentsSet predictedB = modelB.posteriorAlignments(sentences,
				sentenceSource, 1f , projectPosteriors,false);
		
		for(int i = 0; i < predictedF.size(); i++){
			predictedF.get(i).resetPoints();
			predictedB.get(i).resetPoints();
		}
		AlignmentsSet predicted = null;
		if(type.equalsIgnoreCase("softIntersection")){
			predicted = AlignmentSymetrization.softIntersection(predictedF, predictedB, threshold);			
		}else if(type.equalsIgnoreCase("softUnion")){
			predicted = AlignmentSymetrization.softUnion(predictedF, predictedB, threshold);
		}else{
			System.out.println("Uknown type exiting");
			System.exit(-1);
		}
		return predicted;
	}

	
	public static void saveAlignment(PrintStream[] alignmentStream,
			Alignment alignment, 
			BilingualCorpus corpus,
			String outputType) throws IOException,
			FileNotFoundException {
		String[] data = null;
		if(outputType.equals("moses")){
			data = alignment.toMosesFormat(corpus);
		}else if(outputType.equals("posterior")){
			data = alignment.toPosteriorFormat(corpus);
		}else{
			System.out.println("Data not defined");
			throw new UnsupportedOperationException();
		}
		alignmentStream[0].println(data[0]);
		alignmentStream[1].println(data[1]);
		alignmentStream[2].println(data[2]);
	}
	
	public static void main(String[] args) throws IOException {
		String corpusDescription = args[0];
		int size = Integer.parseInt(args[1]);
		int maxSentenceSize = Integer.parseInt(args[2]);
		
		System.out.println("Corpus " + corpusDescription);
		System.out.println("Size " + size);
		System.out.println("Max Sent length " + maxSentenceSize);
		
		BilingualCorpus forwardCorpus = BilingualCorpus.getCorpusFromFileDescription(corpusDescription, size,maxSentenceSize);
		BilingualCorpus backwardCorpus = forwardCorpus.reverse();	
	
		String modelDir1 = args[3];
		String modelName1 = args[4];
		double epsilon1 = Double.parseDouble(args[5]);
		double slack1 = Double.parseDouble(args[6]);
		int maxStep1 = Integer.parseInt(args[7]);
		int maxProjecIter1 = Integer.parseInt(args[8]);
		String intersectionType = args[9];
		modelDir1 = modelDir1 + "/" + modelName1 + "/" + forwardCorpus.getName()
		+ "/" + size + "/model/";

		
		
		System.out.println("Model1 ");
		System.out.println("Model Dir " + modelDir1);
		System.out.println("Model Name " + modelName1);
		System.out.println("Epsilon " + epsilon1);
		System.out.println("Slack " + slack1);
		System.out.println("Max Step " + maxStep1);
		System.out.println("Max Project Iterations " + maxProjecIter1);
		
		
		double threshold = Double.parseDouble(args[10]);
		String outputDir = args[11];
		String outputType = args[12];
		
		AbstractModel[] models= GenericMethods.initializeModels(forwardCorpus, backwardCorpus, modelName1, modelDir1, 
				epsilon1, slack1, maxStep1, maxProjecIter1);
	
		AlignmentsSet symmetric= getSymmetrizationAlignments
		(forwardCorpus, BilingualCorpus.TRAIN_CORPUS, true, models[0], models[1], intersectionType, threshold);
		
		//create outputStream
		PrintStream[] stream = new PrintStream[3];
		initializeStream(stream, forwardCorpus, intersectionType, 
				modelName1, size, outputDir, threshold, outputType);
		for(Alignment al: symmetric._alignments){		
			saveAlignment(stream, al, forwardCorpus, outputType);
		}
		stream[0].close();
		stream[1].close();
		stream[2].close();
	}
	
}

